package org.glandais.profiler.beans;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Stack;

public class TraceStack {

	private static final DateFormat DATE_TIME_INSTANCE = SimpleDateFormat
			.getDateTimeInstance();

	public MethodTrace entryMethod;
	public String threadName = Thread.currentThread().getName();
	public String threadId = Long.toHexString(Thread.currentThread().getId());
	public Stack<MethodTrace> stack = new Stack<MethodTrace>();

	public long stackStart;

	public transient ProcessingList processingNanos;

	public void removeProcessing() {
		removeProcessing(entryMethod);
	}

	private enum Position {
		avant, pendant, apres;
	}

	private Position getPosition(long t, MethodTrace method) {
		if (t < method.startSystemNanoTime) {
			return Position.avant;
		}
		if (t > method.getEndSystemNanoTime()) {
			return Position.apres;
		}
		return Position.pendant;
	}

	private void removeProcessing(MethodTrace method) {
		long d_debut = 0;
		long d_duration = 0;
		for (ProcessingTrace trace : processingNanos.processingTraces) {
			Position debutTrace = getPosition(trace.startSystemNanoTime, method);
			Position finTrace = getPosition(trace.getEndSystemNanoTime(),
					method);
			if (finTrace == Position.avant) {
				d_debut = d_debut - trace.durationNano;
			} else if (debutTrace == Position.avant
					&& finTrace == Position.pendant) {
				d_duration = d_duration
						- (trace.getEndSystemNanoTime() - method.startSystemNanoTime);
				d_debut = d_debut - trace.durationNano;
			} else if (debutTrace == Position.pendant
					&& finTrace == Position.pendant) {
				d_duration = d_duration - trace.durationNano;
			} else if (debutTrace == Position.pendant
					&& finTrace == Position.apres) {
				d_duration = d_duration
						- (method.getEndSystemNanoTime() - trace.startSystemNanoTime);
			}
		}
		method.startSystemNanoTime = method.startSystemNanoTime + d_debut;
		method.durationNano = method.durationNano + d_duration;

		for (MethodTrace subMethod : method.subMethods) {
			removeProcessing(subMethod);
		}
	}

	/*
	private boolean traceAvantMethode(ProcessingTrace trace, MethodTrace method) {
		if (trace.getEndSystemNanoTime() < method.startSystemNanoTime)
			return true;
		return false;
	}

	private boolean debutTraceDansMethode(ProcessingTrace trace,
			MethodTrace method) {
		return dansMethode(trace.startSystemNanoTime, method);
	}

	private boolean finTraceDansMethode(ProcessingTrace trace,
			MethodTrace method) {
		return dansMethode(trace.getEndSystemNanoTime(), method);
	}

	private boolean dansMethode(long t, MethodTrace method) {
		if (t > method.startSystemNanoTime) {
			if (t < method.getEndSystemNanoTime()) {
				return true;
			}
		}
		return false;
	}
	*/

	@Override
	public String toString() {
		SimpleDateFormat.getDateTimeInstance();
		StringBuilder sb = new StringBuilder(DATE_TIME_INSTANCE
				.format(new Date(stackStart)));
		sb.append(" - ").append(entryMethod.getDurationMillis())
				.append("ms - ").append(entryMethod.signature);
		return sb.toString();
	}
}
